/**
 * \file Файл описания класса Plot2D
 *
 * Файл содержит определение класса для отрисовки графиков на холсте
 */
#ifndef PLOT2D_H
#define PLOT2D_H

#include <glibmm/object.h>
#include <glibmm/ustring.h>
#include <gdkmm/rgba.h>
#include <gtkmm/drawingarea.h>
#include <boost/container/vector.hpp>
#include "plot2d.h"
#include <boost/range/algorithm/find.hpp>
#include <boost/container/vector.hpp>
#include <boost/array.hpp>
#include <boost/algorithm/minmax_element.hpp>
#include <boost/lexical_cast.hpp>
#include <iostream>
#include <gtkmm/gestureclick.h>
#include <gtkmm/eventcontrollermotion.h>
#include<gtkmm/eventcontrollerscroll.h>

#include "plotdata2d.h"

using namespace boost;
using namespace Glib;

/**
 * @brief Класс рисования графиков на холсте
 *
 * Класс отнаследован от класса Gtk::DrawingArea
 * рисует графики, обрабатывает события от мышки
 * масштабирует графики по осям
 *
 */
class Plot2D : public Gtk::DrawingArea {
        Plot2D &operator = (const Plot2D &) = delete;
        Plot2D(const Plot2D &) = delete;

    protected:
        ustring m_plot_title;///<название холста
        ustring m_current_axes_name;///<название графика для которого отображаются шкалы на холсте
        container::vector<PlotData2D*> m_plot_data;///<указатели на обЪекты для отрисовки графиков
        PlotData2D* m_PlotData2D_temp;///< временный обЪект для извлечения данных из нужного графика
        double m_interval_begin;///< индекс массива данных для начала отрисовки графиков
        double m_interval_end;///< индекс массива данных для конца отрисовки графиков (если 0- то до конца массива)
        double m_interval_begin_temp;///< для масштабирования и сдвига по оси Х
        double m_interval_end_temp;///< для масштабирования и сдвига по оси Х
        double m_StartPosX;///< координата Х при нажатии мыши на холсте
        double m_StartPosY;///< координата Y при нажатии мыши на холсте
        double m_Y_offset_min;///< добавка к минимуму по оси Y для масштабирования и сдвига оси
        double m_Y_offset_max;///< добавка к максимуму по оси Y для масштабирования и сдвига оси
        double m_delta;///<значения сдвига графиков по оси Y(% от разницы Ymax-Ymin)
        bool m_MotionOn;///<флаг определения перемещения мышки на холсте
        uint32_t m_maxSize;///< максимальное количество элементов в массиве данных
        OnDrawSignals OnDrawState {OnDrawSignals ::IdlePLot};
        /**
         * @brief функция перерисовки для cairo
         *
         * @param cr контекст cairo
         * @param width ширина холста
         * @param height высота холста
         */
        void OnDraw(const Cairo::RefPtr<Cairo::Context> &cr,
                    uint16_t width,
                    uint16_t height);

        /**
         * @brief отрисовка графиков на холсте
         *
         * @param cr контекст cairo
         * @param width ширина холста
         * @param height высота холста
         */
        void PlotsDrawing(const ::Cairo::RefPtr<::Cairo::Context> &cr,
                          uint16_t width,
                          uint16_t height);

        /**
         * @brief отрисовка осей на холсте
         *
         * @param cr контекст cairo
         * @param width ширина холста
         * @param height высота холста
         */
        void AxesDrawing(const ::Cairo::RefPtr<::Cairo::Context> &cr,
                         uint16_t width,
                         uint16_t height);

        /**
         * @brief обработка нажатия мыши на холсте
         *
         * @param n_press количество нажатий
         * @param x координата Х нажатия
         * @param y координата Y нажатия
         */
        void MouseButtonPressed(int n_press,
                                double x,
                                double y);

        /**
         * @brief обработка отпускания мыши на холсте
         *
         * @param n_press количество нажатий
         * @param x координата Х отпускания
         * @param y координата Y отпускания
         */
        void MouseButtonReleased(int n_press,
                                 double x,
                                 double y);

        /**
         * @brief обработка перемещения курсора при нажатой мышки и изменения диапазона шкалы оси Y
         *
         * @param x координата Х перемещения
         * @param y координата Y перемещения
         */
        void Motioning(double x,
                       double y);

        /**
         * @brief обработка скроллинга на холсте
         *
         * @param dx скроллинг по Х
         * @param dy скроллинг по Y
         * @return bool скроллинг активен
         */
        bool Scrolling(double dx,
                       double dy);

    public:

        /**
         * @brief Конструктор класса
         *
         */
        Plot2D();

        /**
         * @brief отрисовка всех доступных графиков
         *
         * @param axes_name имя графика для отрисовки шкала по X и y
         * @param interval_begin индекс массива данных для начала отрисовки
         * @param interval_end индекс массива данных для конца отрисовки (Если 0 - то до конца массива)
         * @param y_offset_min добавка к минимуму по оси Y для масштабирования и сдвига оси (% от диапазона шкалы)
         * @param y_offset_max добавка к максимуму по оси Y для масштабирования и сдвига оси (% от диапазона шкалы)
         */
        void PlotDraw(ustring axes_name,
                      double interval_begin,
                      double interval_end,
                      double y_offset_min,
                      double y_offset_max);

        /**
         * @brief добавление графика на холост
         *
         * @param data указатель на данные для графика
         */
        void AddDataToPlot(PlotData2D *data);


};

#endif // PLOT2D_H
